﻿//AcademicPlanner - course registration planning web app.
//Copyright (C) 2009  Boubacar Diallo

//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.


using System;
using System.Collections.Generic;
using System.Linq;
using AcademicPlanner.Data;
using AcademicPlanner.Data.Entities;
using AcademicPlanner.Data.Repositories;

namespace AcademicPlanner.Domain.Models.Collections
{
	/// <summary>
	/// PersonCollection represents a collection of <c>Person</c>s.
	/// </summary>
	/// <version>1.0</version>
	/// <since>1.0</since>
	public class PersonCollection : ModelCollection<Person, PersonEntityRepository, PersonEntity>
	{
		/// <summary>
		/// Gets the data layer repository of the underlying <c>PersonEntity</c>s of this collection's <c>Person</c>s.
		/// </summary>
		/// <version>1.0</version>
		/// <since>1.0</since>
		protected override PersonEntityRepository EntityRepo { get { return DomainMaster.DSAS.PersonEntityRepo; } }


		/// <summary>
		/// No argument constructor; invokes the matching base class constructor.
		/// </summary>
		/// <seealso cref="M:AcademicPlanner.Domain.ModelCollection(TModel, TEntityRepo, TREntity).ModelCollection"/>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public PersonCollection()
			: base()
		{

		}


		/// <summary>
		/// Filters this PersonCollection to return only the <c>Person</c> with the given
		/// email address. This method relies on this PersonCollection's 
		/// <see cref="P:EntityRepo"/> to find the matching <c>PersonEntity</c> then creates
		/// the <c>Person</c> represented by that <c>PersonEntity</c>.
		/// </summary>
		/// <param name="pEmail">The email address.</param>
		/// <returns>The <c>Person</c> having the given email or <c>null</c>.</returns>
		/// <exception cref="T:AcademicPlanner.Domain.CriticalDomainException">
		/// Thrown with an error code of <c>DomainErrorCode.M_PERSON_ENTITY_RETRIEVAL_BY_EMAIL_FAILURE</c>
		/// when a <see cref="T:AcademicPlanner.Data.DataException"/> occurs;
		/// the <see cref="T:AcademicPlanner.Data.DataException"/> is accessible through the
		/// <c>InnerException</c> property.
		/// </exception>
		/// <seealso cref="P:AcademicPlanner.Domain.DomainMaster.ModelsFountain"/>
		/// <seealso cref="M:AcademicPlanner.Domain.ModelsFountain.GetPerson"/>
		/// <seealso cref="P:EntityRepo"/>
		/// <seealso cref="M:AcademicPlanner.Data.PersonEntityRepository.FindByEmail"/>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public Person WithEmail(string pEmail)
		{
			Person rPers = null;
			PersonEntity vEnt = null;

			try
			{
				vEnt = EntityRepo.FindByEmail(pEmail);
			}
			catch (DataException vDx)
			{
				var vCx = new CriticalDomainException(DomainErrorCode.M_PERSON_ENTITY_RETRIEVAL_BY_EMAIL_FAILURE, vDx);
				throw vCx;
			}

			if (vEnt != null)
				rPers = DomainMaster.ModelsFountain.GetPerson(vEnt);

			return rPers;
		}

		/// <summary>
		/// Filters this PersonCollection to return only the <c>Person</c> having an
		/// <c>Account</c>'s <c>User</c> with the given username. This method relies 
		/// on this PersonCollection's <see cref="P:EntityRepo"/> to find the matching
		/// <c>PersonEntity</c> then creates the <c>Person</c> represented by that 
		/// <c>PersonEntity</c>.
		/// </summary>
		/// <param name="pAccountUserName">The username.</param>
		/// <returns>
		/// The <c>Person</c> having an <c>Account</c>'s <c>User</c> with the given 
		/// username or <c>null</c>.
		/// </returns>
		/// <exception cref="T:AcademicPlanner.Domain.CriticalDomainException">
		/// Thrown with an error code of <c>DomainErrorCode.M_PERSON_ENTITY_RETRIEVAL_BY_ACCOUNT_USER_NAME_FAILURE</c>
		/// when a <see cref="T:AcademicPlanner.Data.DataException"/> occurs;
		/// the <see cref="T:AcademicPlanner.Data.DataException"/> is accessible through the
		/// <c>InnerException</c> property.
		/// </exception>
		/// <seealso cref="P:AcademicPlanner.Domain.DomainMaster.ModelsFountain"/>
		/// <seealso cref="M:AcademicPlanner.Domain.ModelsFountain.GetPerson"/>
		/// <seealso cref="P:EntityRepo"/>
		/// <seealso cref="M:AcademicPlanner.Data.PersonEntityRepository.FindByAccountUserName"/>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public Person WithAccountUserName(string pAccountUserName)
		{
			Person rPers = null;
			PersonEntity vEnt = null;

			try
			{
				vEnt = EntityRepo.FindByAccountEntityUserEntityName(pAccountUserName);
			}
			catch (DataException vDx)
			{
				var vCx = new CriticalDomainException(DomainErrorCode.M_PERSON_ENTITY_RETRIEVAL_BY_ACCOUNT_USER_NAME_FAILURE, vDx);
				throw vCx;
			}

			if (vEnt != null)
				rPers = DomainMaster.ModelsFountain.GetPerson(vEnt);

			return rPers;
		}
	}
}
